﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Cms.EntLib;

namespace Cms.BLL
{
    public enum XmlFormType
    {
        Query,//查询页面
        Model//编辑页
    }
    public class ParseXmlForm
    {
        private string xmlstring;
        private XmlDocument Doc = null;
        private XmlFormType xmlFormType = XmlFormType.Model;
        private string ListLayOutID = null;
        public int FormWidth;
        public int FormHeight;
        /// <summary>
        /// 需要引用的文件
        /// </summary>
        public List<string> Requires;

        /// <summary>
        /// 页面初始化的时候需要加载的JS代码段.
        /// </summary>
        public List<string> InitScripts;
        public ParseXmlForm(string url)
        {
            if (!String.IsNullOrEmpty(url))
            {
                this.xmlstring = url;
                Doc = new XmlDocument();
                Doc.LoadXml(url);
                Requires = new List<string>();
                InitScripts = new List<string>();
                InitScripts.Add(" var jqGridList=[];");
            }
        }
        public ParseXmlForm(string url, XmlFormType xmlformType, string listid)
            : this(url)
        {
            // ParseXmlForm(url);
            this.xmlFormType = xmlformType;
            ListLayOutID = listid;

        }
        //public ParseXmlForm(string XmlString,string 
        public void AddRequires(string requires)
        {
            if (!this.Requires.Contains(requires))
                this.Requires.Add(requires);
        }
        public void AddInitScripts(string scripts)
        {
            this.InitScripts.Add(scripts);
        }

        /// <summary>
        /// 构造控件的样式
        /// </summary>
        /// <param name="dock"></param>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private string BuilderStyle(string dock, string left, string top, string width, string height)
        {
            StringBuilder sb = new StringBuilder();
            if (String.IsNullOrEmpty(dock) || dock == "none")
            {
                if (!String.IsNullOrEmpty(left) || !String.IsNullOrEmpty(top) || !String.IsNullOrEmpty(width) || !string.IsNullOrEmpty(height))
                {
                    sb.Append("style='");
                    if (!String.IsNullOrEmpty(left))
                        sb.AppendFormat("left:{0}px;", left);
                    if (!String.IsNullOrEmpty(top))
                        sb.AppendFormat("top:{0}px;", top);
                    if (!String.IsNullOrEmpty(width))
                        sb.AppendFormat("width:{0}px;", width);
                    if (!String.IsNullOrEmpty(height))
                        sb.AppendFormat("height:{0}px", height);
                    sb.Append("'");
                }
            }
            else
            {
                switch (dock.ToLower())
                {
                    case "fill":
                        sb.AppendFormat(" dock='{0}' ", dock);
                        break;
                    case "top":
                    case "bottom":
                        sb.AppendFormat(" dock='{0}' style='height:{1}px' ", dock, String.IsNullOrEmpty(height) ? "200" : height);
                        break;
                    case "left":
                    case "width":
                        sb.AppendFormat(" dock='{0}' style='width:{1}px' ", dock, width);
                        break;
                    default:
                        sb.AppendFormat(" dock='{0}' ", dock);
                        break;
                }
            }
            return sb.ToString();
        }

        /// <summary>
        ///解析控件.
        /// </summary>
        /// <param name="xn"></param>
        /// <returns></returns>
        public string ParseControl(XmlNode xn)
        {
            StringBuilder sbXml = new StringBuilder();
            if (xn.Name.CompareTo("Control") == 0 || xn.Name.CompareTo("children") == 0)
            {
                string alias = Utiltiy.GetXmlChildText(xn, "alias");
                string key = Utiltiy.GetXmlChildText(xn, "key");
                string caption = Utiltiy.GetXmlChildText(xn, "properties/caption");
                string dock = Utiltiy.GetXmlChildText(xn, "properties/dock");
                string left = Utiltiy.GetXmlChildText(xn, "properties/left");
                string top = Utiltiy.GetXmlChildText(xn, "properties/top");
                string width = Utiltiy.GetXmlChildText(xn, "properties/width");
                string height = Utiltiy.GetXmlChildText(xn, "properties/height");
                string dataField = Utiltiy.GetXmlChildText(xn, "properties/dataField");
                switch (key)
                {
                    case "linb.UI.Group":
                        sbXml.AppendFormat("<fieldset id='{0}' class='group {1}'", alias, String.IsNullOrEmpty(dock) ? "" : "dock");
                        if (!String.IsNullOrEmpty(dock))
                        {
                            AddRequires("dock");
                        }
                        sbXml.AppendLine(BuilderStyle(dock, left, top, width, height));
                        sbXml.Append(">");
                        sbXml.AppendFormat("<legend>{0}</legend>", caption);
                        sbXml.Append("<div class='group-inner'>");
                        foreach (XmlNode xnChild in xn.SelectNodes("children"))
                        {
                            sbXml.AppendLine(ParseControl(xnChild));
                        }
                        sbXml.AppendLine("</div>");
                        sbXml.AppendLine("</fieldset>");
                        break;
                    case "linb.UI.Input":
                        if (!String.IsNullOrEmpty(width) && !String.IsNullOrEmpty(height))
                        {
                            //多行的.
                            sbXml.Append("<div class='input memo'");
                            sbXml.Append(BuilderStyle(dock, left, top, width, height));
                            sbXml.Append(">");
                            sbXml.AppendFormat("<textarea type='text' name='{0}'></textarea>", dataField);
                            sbXml.Append("</div>");
                        }
                        else
                        {
                            sbXml.Append("<div class='input'");
                            sbXml.Append(BuilderStyle(dock, left, top, width, height));
                            sbXml.Append(">");
                            sbXml.AppendFormat("<input type='text' name='{0}'/>", dataField);
                            sbXml.Append("</div>");
                        }
                        break;
                    case "linb.UI.SLabel":
                        sbXml.Append("<div class='label'");
                        sbXml.Append(BuilderStyle(dock, left, top, width, height));
                        sbXml.Append(">");
                        sbXml.Append(caption);
                        sbXml.Append("</div>");
                        break;
                    case "linb.UI.SButton":
                        sbXml.Append("<div class='button'");
                        sbXml.Append(BuilderStyle(dock, left, top, width, height));
                        sbXml.Append(">");
                        sbXml.AppendFormat("<button id='{1}'>{0}</button>", caption, alias);
                        sbXml.Append("</div>");
                        break;
                    case "linb.UI.ComboInput":
                        sbXml.Append(ParseComboInput(xn));
                        break;
                    case "linb.UI.SCheckBox":
                        sbXml.Append(ParseCheckBox(xn));
                        break;
                    case "linb.UI.TreeGrid":
                        AddRequires("TreeGrid");
                        sbXml.Append(ParseGrid(xn));
                        break;
                    case "linb.UI.RichEditor":
                        sbXml.Append("<div class='richeditor'");
                        sbXml.Append(BuilderStyle(dock, left, top, width, height));
                        sbXml.Append(">");
                        sbXml.AppendFormat("<textarea id='{0}' name='{0}'></textarea>", alias);
                        sbXml.Append("</div>");
                        AddRequires("RichEditor");
                        break;
                }
            }
            return sbXml.ToString();
        }
        public string ParseCheckBox(XmlNode xn) {
            StringBuilder sb = new StringBuilder();
            string alias = EntLib.Utiltiy.GetXmlChildText(xn, "alias");
            string key = Utiltiy.GetXmlChildText(xn, "key");
            string left = Utiltiy.GetXmlChildText(xn, "properties/left");
            string top = Utiltiy.GetXmlChildText(xn, "properties/top");
            string width = Utiltiy.GetXmlChildText(xn, "properties/width");
            string height = Utiltiy.GetXmlChildText(xn, "properties/height");
            string dataField = Utiltiy.GetXmlChildText(xn, "properties/dataField");
            string caption = Utiltiy.GetXmlChildText(xn, "properties/caption");
            sb.Append("<div class='checkbox' ");
            sb.Append(BuilderStyle("",left,top,width,height));
            sb.Append(">");
            sb.AppendFormat("<input type='checkbox' name='{0}' id='{1}'/><label for='{1}'>{2}</label>",dataField,System.Guid.NewGuid().ToString(),caption);
            return sb.ToString();

        }
        /// <summary>
        /// 解析下拉控件.
        /// </summary>
        /// <param name="xn"></param>
        /// <returns></returns>
        public string ParseComboInput(XmlNode xn)
        {
            StringBuilder sb = new StringBuilder();
            string alias = EntLib.Utiltiy.GetXmlChildText(xn, "alias");
            string key = Utiltiy.GetXmlChildText(xn, "key");
            string left = Utiltiy.GetXmlChildText(xn, "properties/left");
            string top = Utiltiy.GetXmlChildText(xn, "properties/top");
            string width = Utiltiy.GetXmlChildText(xn, "properties/width");
            string height = Utiltiy.GetXmlChildText(xn, "properties/height");
            string dataField = Utiltiy.GetXmlChildText(xn, "properties/dataField");
            sb.Append("<div class='combobox' ");
            sb.Append(BuilderStyle("", left, top, width, height));
            sb.Append(">");
            sb.AppendFormat("<select id='{0}' name='{0}'>", alias);
            XmlNodeList xnl = Utiltiy.GetXmlChildList(xn, "properties/items");
            foreach (XmlNode x in xnl)
            {
                sb.AppendFormat("<option value='{0}' {2}>{1}</option>", Utiltiy.GetXmlChildText(x, "id"), Utiltiy.GetXmlChildText(x, "caption"), Utiltiy.GetXmlChildText(x, "caption"));
            }
            sb.Append("</select>");
            sb.Append("</div>");
            return sb.ToString();
        }


        public static string[] GetGridCol(XmlNode Rows)
        {
            string[] result = new string[3];
            bool haveSumList = false;
            StringBuilder colNames = new StringBuilder();
            StringBuilder colModel = new StringBuilder();
            XmlNodeList xnl = Rows.SelectNodes("properties/header");
            int totalWidth = 0;
            bool KeyFlag = false;
            List<string> collist = new List<string>();
            string KeyField = "";
            foreach (XmlNode xn in xnl)
            {
                string title = xn.SelectSingleNode("caption") == null ? "" : xn.SelectSingleNode("caption").InnerText;
                string name = xn.SelectSingleNode("id") == null ? "" : xn.SelectSingleNode("id").InnerText;
                string editable = xn.SelectSingleNode("editable") == null ? "0" : xn.SelectSingleNode("editable").InnerText;
                bool allowedit = false;
                //string nodename = xn.Name;
                //string editable = Readonly == "1" ? "false" : "true";
                if (editable == "1" || editable == "true")
                    allowedit = true;
                string key = xn.SelectSingleNode("key") == null ? "" : xn.SelectSingleNode("key").InnerText.ToLower();
                bool iskey = false;
                if (!String.IsNullOrEmpty(key) && key == "true")
                    iskey = true;
                string type = xn.SelectSingleNode("type") == null ? "1" : xn.SelectSingleNode("type").InnerText;
                string visible = xn.SelectSingleNode("visible") == null ? "1" : xn.SelectSingleNode("visible").InnerText;
                //string newtype = xn.SelectSingleNode("newtype") == null ? "" : xn.SelectSingleNode("newtype").InnerText;
                string sqltext = xn.SelectSingleNode("sqltext") == null ? "" : xn.SelectSingleNode("sqltext").InnerText;
                string colName = name;//(String.IsNullOrEmpty(name) ? nodename : name).ToLower();
                string width = xn.SelectSingleNode("width") == null ? String.Format("{0}", colName.Length * 12) : xn.SelectSingleNode("width").InnerText;
                string formula = "";// (xmlSc == null || xmlSc.SelectSingleNode(nodename.ToLower() + "/formula") == null) ? "" : xmlSc.SelectSingleNode(nodename.ToLower() + "/formula").InnerText;
                formula = formula.Replace(System.Environment.NewLine, "");
                string edittype = "";
                string editoptions = "";
                string formatter = "";
                string align = "";
                string editrules = "";
                /*
                    TdxDBDateColumn
                 */
                switch (type)
                {
                    case "label"://标签； 
                        edittype = "";
                        allowedit = false;
                        break;
                    case "button"://按钮； 
                    case "input"://输入框； 
                    case "textarea"://多行输入框；
                    case "number"://数字输入框；
                        edittype = "text";
                        editrules = "number:true";
                        break;
                    case "progress"://进程框；
                        break;
                    case "combobox"://下拉列表输入框；
                    case "listbox"://只读下拉列表输入框；
                    case "getter"://获得数据输入框； 
                    case "helpinput"://辅助下拉列表输入框
                    case "cmdbox"://命令输入框； 
                    case "popbox"://弹出窗口输入框；
                        edittype = "select";
                        string pickstring = "";
                        if (String.IsNullOrEmpty(pickstring))
                            editoptions = String.Format("dataUrl: \"{0}\"", sqltext);
                        else
                        {
                            string[] picks = pickstring.Split(System.Environment.NewLine.ToCharArray());
                            string editvalue = "";
                            foreach (string s in picks)
                            {
                                if (!String.IsNullOrEmpty(s))
                                    editvalue += String.Format("{0}:{0};", s);
                            }
                            editoptions = "value:\"" + editvalue.TrimEnd(';') + "\"";
                        }
                        break;
                    case "time"://时间下拉列表输入框； 
                        formatter = "time";
                        break;
                    case "date"://日期下拉列表输入框； 
                        edittype = "custom";
                        editoptions = "custom_element:custom_grid_createdate,custom_value:custom_grid_getdate";
                        formatter = "date";
                        break;
                    case "color"://颜色下拉列表输入框； 
                        break;
                    default:
                        edittype = "text";
                        break;
                }


                int iw = 0;
                if (width != "" && int.TryParse(width, out iw))
                {
                    if (visible == "1")
                        totalWidth += iw;
                    colNames.AppendFormat("'{0}',", title);//标题
                    colModel.AppendLine("{");
                    colModel.AppendFormat("name:'{0}',index:'{0}',width:{1}", colName, width);
                    if (allowedit)
                    {
                        colModel.Append(",editable:true");
                        if (edittype != "text")
                        {
                            colModel.AppendFormat(",editable:true,edittype:'{0}'", edittype);
                        }
                    }
                    colModel.AppendFormat(",fixed:true");
                    if (iskey)
                        colModel.AppendFormat(",key:true");
                    if (visible != "1")
                    {
                        colModel.Append(",hidden:true");
                    }
                    if (!String.IsNullOrEmpty(formula))
                    {
                        colModel.AppendFormat(",formula:\"{0}\"", formula);
                    }
                    if (!String.IsNullOrEmpty(editoptions))
                        colModel.AppendFormat(",editoptions:{0}", editoptions);
                    if (!String.IsNullOrEmpty(formatter))
                        colModel.AppendFormat(",formatter:'{0}'", formatter);
                    if (!String.IsNullOrEmpty(align))
                        colModel.AppendFormat(",align:'{0}'", align);
                    if (!String.IsNullOrEmpty(editrules))
                        colModel.Append(",editrules:{" + editrules + "}");
                    colModel.Append("},");
                    collist.Add(colName);
                }
            }
            result[0] = colNames.ToString().TrimEnd(',');
            result[1] = colModel.ToString().TrimEnd(',');
            result[2] = totalWidth.ToString();
            return result;
        }
        /// <summary>
        /// 解析表格控件
        /// </summary>
        /// <param name="xn"></param>
        /// <returns></returns>
        public string ParseGrid(XmlNode XnControl)
        {
            StringBuilder Result = new StringBuilder();
            string alias = Utiltiy.GetXmlChildText(XnControl, "alias");
            string key = Utiltiy.GetXmlChildText(XnControl, "key");
            string left = Utiltiy.GetXmlChildText(XnControl, "properties/left");
            string top = Utiltiy.GetXmlChildText(XnControl, "properties/top");
            string width = Utiltiy.GetXmlChildText(XnControl, "properties/width");
            string height = Utiltiy.GetXmlChildText(XnControl, "properties/height");
            string dataField = Utiltiy.GetXmlChildText(XnControl, "properties/dataField");
            string dock = Utiltiy.GetXmlChildText(XnControl, "properties/dock");
            string title = "";
            if (String.IsNullOrEmpty(dock))
                dock = "fill";
            if (!String.IsNullOrEmpty(dock) && dock != "none")
            {
                AddRequires("dock");
            }

            Result.AppendFormat("<div class='grid {1}' id='div_{0}' ", alias, String.IsNullOrEmpty(dock) || dock == "none" ? "" : "dock");
            Result.Append(BuilderStyle(dock, left, top, width, height));
            Result.Append(">");


            Result.AppendFormat("<table id='{0}'></table>", alias);
            Result.AppendFormat("<div id='pager{0}'></div>", alias);
            //构造jqgrid
            Result.AppendLine("<script type='text/javascript'>");
            //将表格名缓存到列表里.
            //Result.AppendLine(" jqGridList.push('" + alias + "');");
            AddInitScripts("jqGridList.push({id:'" + alias + "',name:'" + dataField + "'});");

            string[] col = GetGridCol(XnControl);

            Result.AppendLine("function InitGrid_" + alias + "(w,h){");
            Result.AppendFormat("var _w={0};", String.IsNullOrEmpty(width) ? col[2] : width);
            Result.AppendFormat("var _h={0};", String.IsNullOrEmpty(height) ? "200" : height);
            Result.Append("if(!w)w=_w;if(!h)h=_h;");
            Result.AppendFormat("jQuery('#{0}').jqGrid(\r\n", alias);
            if (xmlFormType == XmlFormType.Model)
                Result.AppendLine("{datatype: 'local',");
            else
            {
                Result.AppendLine("{datatype: 'json',");
                Result.AppendFormat("url:'/tools/json.ashx?param=getquerylist&id={0}',", this.ListLayOutID);
                Result.AppendLine("jsonReader:{ root: \"rows\", page: \"page\", total: \"total\", records: \"records\", repeatitems: false, cell:\"cell\", id: \"Id\", userdata: \"userdata\", subgrid: { root: \"rows\", repeatitems: true, cell: \"cell\"} },");
            }

            //不用URL.
            //Result.AppendFormat("url:{0},\r\n", url);
            //客户端提交
            Result.AppendLine("cellsubmit:'clientArray',");
            //可以指不分页.
            Result.AppendLine("rowNum:999,");

            Result.Append("width:w,");
            //  if (!string.IsNullOrEmpty(height))
            Result.Append("height: h,\r\n");
            Result.AppendFormat("capiton:'{0}',\r\n", title);
            Result.AppendFormat("pager:'#pager{0}',", alias);
            Result.AppendLine("forceFit:false,hidedlg: true,");

            //Result.AppendLine("jsonReader:jgGridjsonReader,");
            Result.AppendLine("colNames:[");
            Result.AppendLine(col[0]);
            Result.AppendLine("],");
            Result.AppendLine("colModel:[");
            Result.AppendLine(col[1]);
            Result.AppendLine("],");
            Result.AppendLine("onSelectRow: function(id) {");
            Result.AppendFormat("GridRowSelect('{0}',id)", alias);
            Result.AppendLine(" },");
            Result.AppendLine("loadComplete: function(data) {");
            Result.AppendLine(" if(typeof(gridcomplete)=='function'){gridcomplete('" + alias + "',data);}");
            Result.AppendLine("}");
            Result.AppendLine("});");
            Result.AppendLine("}");

            Result.AppendLine("</script>");
            Result.Append("</div>");


            return Result.ToString();
        }

        //解析
        public string Parse()
        {
            StringBuilder sb = new StringBuilder();
            if (Doc != null)
            {
                XmlNode XnForm = Doc.SelectSingleNode("Form");
                string w = Utiltiy.GetXmlChildText(XnForm, "viewSize/width");
                string h = Utiltiy.GetXmlChildText(XnForm, "viewSize/height");
                int.TryParse(w, out this.FormWidth);
                int.TryParse(h, out this.FormHeight);

                XmlNodeList XnFormControls = XnForm.ChildNodes;
                StringBuilder sbXml = new StringBuilder();

                foreach (XmlNode xn in XnFormControls)
                {
                    sb.Append(ParseControl(xn));
                }
            }
            return sb.ToString();

        }

    }
}
